﻿using gt.IdentityServer.Services;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace gt.IdentityServer.Extensions
{
    public class AppResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        private ILoginService _loginService;
        private ILogger<AppResourceOwnerPasswordValidator> _logger;
        public AppResourceOwnerPasswordValidator(ILoginService loginService,
            ILogger<AppResourceOwnerPasswordValidator> logger)
        {
            _loginService = loginService;
            _logger = logger;
        }

        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            var user = await _loginService.FindLoginUserAsync(context.UserName, context.Password);
            if (user == null)
            {
                _logger.LogDebug($"can't find login user by username:{context.UserName}");
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
            }
            else
            {
                //调用此方法以后内部会进行过滤，只将用户请求的Claim加入到 context.IssuedClaims 集合中 这样我们的请求方便能正常获取到所需Claim

                //验证通过返回结果 
                //subjectId 为用户唯一标识 一般为用户id
                //authenticationMethod 描述自定义授权类型的认证方法 
                //authTime 授权时间
                //claims 需要返回的用户身份信息单元 此处应该根据我们从数据库读取到的用户信息 添加Claims 如果是从数据库中读取角色信息，那么我们应该在此处添加 此处只返回必要的Claim
                var claims = _loginService.GetClaims(user);
                context.Result = new GrantValidationResult(
                    user.Id.ToString(),
                    OidcConstants.AuthenticationMethods.Password, DateTime.UtcNow, claims);
            }
            await Task.CompletedTask;
        }
    }
}
